/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package physicsim;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.text.DecimalFormat;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

/**
 * Copyright 2011 Nick Stanish
 * this program is distributed under the terms of the GNU General Public License v3
 * 
 */

public class Main extends JFrame{


    private static class GameBoard extends Canvas{

       

        DecimalFormat d3Form = new DecimalFormat("#.###");
        DecimalFormat d2Form = new DecimalFormat("#.##");
        DecimalFormat integer = new DecimalFormat("#");
        public String fps = "0 fps";
        public String error = "";
        public String Height;
        public double finalVelocity = 0;
        public double time = 0.000;
        public double refresh = .033;
        public boolean originalPaint = false;
        public boolean platform = false;
        public boolean go = false;
        public int height = 150;
        public int refreshRate = Integer.valueOf(integer.format(refresh * 1000)); //convert to integer refresh * 1000;
        public int traveledDist = 0;
        public int velocity = 0;
        public int shape = 20;
        public BufferedImage background = null;
        public BufferedImage Up = null;
        public BufferedImage doubleUp = null;
        public BufferedImage Down = null;
        public BufferedImage doubleDown = null;
        public BufferedImage Ball = null;
        public BufferedImage Reset = null;
        public BufferedImage Start = null;
        public BufferedImage Stop = null;
        private Image mImage;

        javax.swing.Timer refreshTimer = new javax.swing.Timer(refreshRate, new ActionListener() {
          public void actionPerformed(ActionEvent e) {
              if (traveledDist + height >= 550){
                  traveledDist = 550 - height;
              stop();
              repaint();
              }
              else{
              time = time + refresh; //calculates timer
              time = Double.valueOf(d3Form.format(time));
              double dist = (velocity * time) + ((9.8 * time * time) / 2);
              dist = dist / 2;
              traveledDist = Integer.valueOf(integer.format(dist)); //convert to integer
              finalVelocity = velocity + (9.8 * time);
              finalVelocity = Double.valueOf(d2Form.format(finalVelocity));
              if (finalVelocity < 0){
                  finalVelocity = 0 - finalVelocity;
                 }
              repaint();
              }
          }
       });
       public void stop(){
            go = false;
            fps = "0 fps";
            refreshTimer.stop();
       }
       public void reset(){
           time = 0;
           traveledDist = 0;
           finalVelocity = 0;
           stop();
       }


//***********************************************************
        private class GameListener implements MouseListener {

            public void mouseClicked(MouseEvent e){
                    int mouseX = e.getPoint().x;
                    int mouseY = e.getPoint().y;
                    if (mouseX < 195 && mouseX > 150 && mouseY < 125 && mouseY > 100){
                         if (!go){
                         fps = refreshRate + " fps";
                         go = true;
                         refreshTimer.start();
                        }
                         else {
                         stop();
                        }
                    }
                    if (mouseX < 245 && mouseX > 200 && mouseY < 125 && mouseY > 100){
                        reset();
                    }
                    if(mouseX<175 && mouseX>160 && mouseY>180 && mouseY<195){
                        velocity = velocity - 10;
                    }
                    if(mouseX<195 && mouseX>180 && mouseY>180 && mouseY<195){
                        velocity--;
                    }
                    if(mouseX<265 && mouseX>250 && mouseY>180 && mouseY<195){
                        velocity++;
                    }
                    if(mouseX<285 && mouseX>270 && mouseY>180 && mouseY<195){
                        velocity = velocity + 10;
                    }

            repaint();
            }
            public void mousePressed (MouseEvent e){
            int mouseX = e.getPoint().x;
            int mouseY = e.getPoint().y;
            if (mouseY > (height - 4) && mouseY < (height + 4) && mouseX < 80 && mouseX > 30){
                platform = true;
                } //draggin platform
            }
            public void mouseReleased(MouseEvent e){
                 if (platform){
                platform = false;
                height = e.getPoint().y;
                if ( height < 1) {
                    height = 0;
                }
                if (height >= 550){
                    height = 550;
                }
                } //dragging platform
                 repaint();
            }
            public void mouseEntered(MouseEvent e){

            }
            public void mouseExited (MouseEvent e){}

         }
        //***********************************************************
        @Override
         public void update ( Graphics g ) {
             paint(g); 
         }
        @Override
        public void paint(Graphics g){
            //**
             // Clear the offscreen image.
    Dimension d = getSize();
    checkOffscreenImage();
    Graphics offG = mImage.getGraphics();
    offG.setColor(getBackground());
    offG.fillRect(0, 0, d.width, d.height);
    // Draw into the offscreen image.
    paintOffscreen(mImage.getGraphics());
    // Put the offscreen image on the screen.
    g.drawImage(mImage, 0, 0, null);
            //**
            
        }
        private void checkOffscreenImage() {
    Dimension d = getSize();
    if (mImage == null || mImage.getWidth(null) != d.width
        || mImage.getHeight(null) != d.height) {
      mImage = createImage(d.width, d.height);
    }
  }

  public void paintOffscreen(Graphics g) {
try {
        if (!originalPaint){
    URL url = physicsim.Main.class.getResource("media\\background.png");
	if(url == null) {
		throw new IOException("Couldn't load background.png");
	}
	background = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\Up.png");
	if(url == null) {
		throw new IOException("Couldn't load Up.png");
	}
        Up = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\doubleUp.png");
	if(url == null) {
		throw new IOException("Couldn't load doubleUp.png");
	}
	doubleUp = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\Down.png");
	if(url == null) {
		throw new IOException("Couldn't load Down.png");
	}
	Down = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\doubleDown.png");
	if(url == null) {
		throw new IOException("Couldn't load doubleDown.png");
	}
	doubleDown = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\stop.png");
	if(url == null) {
		throw new IOException("Couldn't load stop.png");
	}
	Stop = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\start.png");
	if(url == null) {
		throw new IOException("Couldn't load start.png");
	}
	Start = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\reset.png");
	if(url == null) {
		throw new IOException("Couldn't load reset.png");
	}
	Reset = ImageIO.read(url);
        url = physicsim.Main.class.getResource("media\\ball.png");
	if(url == null) {
		throw new IOException("Couldn't load ball.png");
	}
	Ball = ImageIO.read(url);
        originalPaint = true;
    }

        g.drawImage(background, 0, 0, null);
        g.drawImage(Up, 250, 180, null);
        g.drawImage(doubleUp, 270, 180, null);
        g.drawImage(Down, 180, 180, null);
        g.drawImage(doubleDown, 160, 180, null);
        g.drawImage(Reset, 200, 100, null);
        if (go){
        g.drawImage(Stop, 150, 100, null);
    }else{
        g.drawImage(Start, 150, 100, null);
    }
        g.drawImage(Ball, 80, (height - shape + traveledDist), null);


} catch(IOException e) {
	error = "" + e;

}

Height = ((550 - height) * 2) + " m";
            g.setColor(Color.BLACK);
            g.drawString(Height, 40, 570);
            g.drawLine(30,550, 30, height); //line to platform
            g.drawLine(30,height, 80, height); //platform
            g.drawString(time + " s", 180, 155);
            g.drawString(velocity + " m/s",200,195);
            g.drawString("initial velocity", 180, 210);
            g.drawString(finalVelocity + " m/s", 100, 570); //m/s counter
            g.drawString(fps,170,570);
            g.drawString(error, 50, 590);
  }
        public GameBoard(){

        setPreferredSize(new Dimension(300, 600));
        setBackground(Color.lightGray);
        addMouseListener(new GameListener());
          }

    }
     public static void main(String[] args) {
        Main game = new Main();
        game.setTitle("Simple Simulation");
        game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GameBoard board = new GameBoard();
        game.add(board);
        game.pack();
        game.setLocationRelativeTo(null);
        game.setVisible(true);
    }

}

